#include "HalSPI.h"
#include "HalGPIO.h"
#include "stm32f4xx_hal_spi.h"

typedef struct
{
    SPI_HandleTypeDef *handle;
    unsigned char cspin;
} HalSPIInfo_t;

// extern SPI_HandleTypeDef hspi1;
extern SPI_HandleTypeDef hspi2;

static HalSPIInfo_t g_spiInfo[HAL_SPI_CHANNEL_COUNT] = {
    {.handle = &hspi2,
     .cspin = 0x1c};

static void spiDelay(void)
{
    //    __NOP();
    //    __NOP();
    //    __NOP();
    //    __NOP();
    //    __NOP();
}

static unsigned char spiWriteRead(SPI_HandleTypeDef *handle, unsigned char txdata)
{
    // HAL_StatusTypeDef status;
    unsigned char rxdata;
    HAL_SPI_TransmitReceive(handle, &txdata, &rxdata, 1, 100);

    return rxdata;
}

void HalSPIRegWrite(HalSPIChannel_t ch, unsigned char reg, unsigned char val)
{
    uint8_t data[2];
    data[0] = reg | 0x80;
    data[1] = val;
    HalGPIOSetLevel(g_spiInfo[ch].cspin, 0);
    // spiDelay();
    // spiWriteRead(g_spiInfo[ch].handle, reg | 0x80);
    // spiWriteRead(g_spiInfo[ch].handle, val);
    HAL_SPI_Transmit(g_spiInfo[ch].handle, data, sizeof(data), 100);
    HalGPIOSetLevel(g_spiInfo[ch].cspin, 1);
}

unsigned char HalSPIRegRead(HalSPIChannel_t ch, unsigned char reg)
{
    unsigned char val;
    uint8_t addr = reg & 0x7f;
    HalGPIOSetLevel(g_spiInfo[ch].cspin, 0);
    // spiDelay();
    // spiWriteRead(g_spiInfo[ch].handle, reg & 0x7F);
    // val = spiWriteRead(g_spiInfo[ch].handle, 0);
    HAL_SPI_Transmit(g_spiInfo[ch].handle, &addr, 1, 100);
    HAL_SPI_Receive(g_spiInfo[ch].handle, &val, 1, 100);
    HalGPIOSetLevel(g_spiInfo[ch].cspin, 1);
    return val;
}

int HalSPIDataWrite(HalSPIChannel_t ch, unsigned char reg, unsigned char *data, unsigned char length)
{
    unsigned char i;
    uint8_t buff[64];

    buff[0] = reg | 0x80;
    for (i = 0; i < length; i++)
    {
        buff[i + 1] = data[i];
    }
    HalGPIOSetLevel(g_spiInfo[ch].cspin, 0);
    // spiDelay();
    // spiWriteRead(g_spiInfo[ch].handle, reg | 0x80);
    // for(i = 0; i < length; i++)
    // {
    //     spiWriteRead(g_spiInfo[ch].handle, data[i]);
    // }
    HAL_SPI_Transmit(g_spiInfo[ch].handle, buff, length + 1, 200);

    HalGPIOSetLevel(g_spiInfo[ch].cspin, 1);
    return i;
}

void HalSPIDataRead(HalSPIChannel_t ch, unsigned char reg, unsigned char *rxbuff, unsigned char length)
{
    unsigned char i;
    uint8_t addr = reg & 0x7f;
    HalGPIOSetLevel(g_spiInfo[ch].cspin, 0);
    // spiDelay();
    // spiWriteRead(g_spiInfo[ch].handle, reg & 0x7F);
    // for (i = 0; i < length; i++)
    // {
    //     rxbuff[i] = spiWriteRead(g_spiInfo[ch].handle, 0);
    // }

    HAL_SPI_Transmit (g_spiInfo[ch].handle, &addr, 1, 100);
    HAL_SPI_Receive (g_spiInfo[ch].handle, rxbuff, length, 200);

    HalGPIOSetLevel(g_spiInfo[ch].cspin, 1);
}

void HalSPIInitialize(void)
{
    int i;

    for (i = 0; i < HAL_SPI_CHANNEL_COUNT; i++)
    {
        HalGPIOConfig(g_spiInfo[i].cspin, HAL_IO_OUTPUT);
    }
}
